package br.edu.univas.locadoragraph.dao;

import java.util.ArrayList;
import java.util.List;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.Index;


import br.edu.univas.locadoragraph.database.Connection;
import br.edu.univas.locadoragraph.database.Keys;
import br.edu.univas.locadoragraph.database.RelTypes;
import br.edu.univas.locadoragraph.to.MovieTO;


public class MovieDAO {
		
		private Connection conn = null;
		private RelationshipGraph relationships;
	public MovieDAO(){
		conn = Connection.getInstance();
		relationships = new RelationshipGraph();
	}
	
	public boolean saveMovieGraph(MovieTO movie){
		System.out.println("Method: Save Movie");

		long start = System.currentTimeMillis();
		GraphDatabaseService graph = conn.newGraphDatabase();
		Index<Node> index = graph.index().forNodes(Keys.INDEXMOVIE);		
		Node node = index.get(Keys.MOVIEKEY, movie.getTitle().toLowerCase()).getSingle();
		if (node == null) {
			Transaction tx = graph.beginTx();
			try {
				node = graph.createNode();
				node.setProperty(Keys.MOVIEKEY, movie.getTitle().toLowerCase());
				node.setProperty("year", movie.getYear());
				node.setProperty("sinopse", movie.getSinopse());
				index.add(node, Keys.MOVIEKEY, movie.getTitle().toLowerCase());
				relationships.createRelationshipMovieActor(graph, node, movie);
				relationships.createRelationshipMovieDirector(graph, node, movie);	
				relationships.createRelationshipMovieGender(graph, node, movie);
				tx.success();
				tx.finish();
				//graph.shutdown();
				double total = (System.currentTimeMillis() - start);
				System.out.println("Movie saved! Time: " + total / 1000);
				return true;
			} catch (Exception e) {
				tx.failure();
				tx.finish();
			} 
			
		}
		//graph.shutdown();
		double total = (System.currentTimeMillis() - start);
		System.out.println("Movie not saved! Time: " + total / 1000);
		return false;
	}
	public boolean updateMovieGraph(MovieTO movie, String key){
		GraphDatabaseService graph = conn.newGraphDatabase();
		Node node = getNodeMovie(graph, key);
		if (node != null) {
			Transaction tx = graph.beginTx();
			try {
				node.setProperty(Keys.INDEXMOVIE, movie.getTitle().toLowerCase());
				node.setProperty("year", movie.getYear());
				node.setProperty("sinopse", movie.getSinopse().toLowerCase());
				node.getSingleRelationship(RelTypes.SERVED, Direction.BOTH).delete();
				node.getSingleRelationship(RelTypes.BELONGS, Direction.BOTH).delete();
				node.getSingleRelationship(RelTypes.DIRECTED, Direction.BOTH).delete();
				relationships.createRelationshipMovieActor(graph, node, movie);
				relationships.createRelationshipMovieDirector(graph, node, movie);	
				relationships.createRelationshipMovieGender(graph, node, movie);
				tx.success();
				tx.finish();
				return true;
				
			} catch (Exception e) {
				tx.failure();
				tx.finish();
				System.err.println("Error: " + e);
			}
		}
		
		return false;
	}
	
	public List<MovieTO> getAllMovie(){
		System.out.println("Method: Get all Movie");
		List<MovieTO> movies = new ArrayList<MovieTO>();
		long start = System.currentTimeMillis();
		GraphDatabaseService graph = conn.newGraphDatabase();
		Index<Node> index = graph.index().forNodes(Keys.INDEXMOVIE);
		Iterable<Node> nodes = index.query(Keys.MOVIEKEY, "*");
		for (Node node : nodes) {
			
			MovieTO movieTO =  new MovieTO();
			movieTO.setTitle((String) node.getProperty(Keys.MOVIEKEY));
			movieTO.setYear((int) node.getProperty("year"));
			movieTO.setSinopse((String) node.getProperty("sinopse"));
			movies.add(movieTO);	
		}
		//graph.shutdown();
		double total = System.currentTimeMillis() - start;
		System.out.println("Time getAllMovie: " + total/1000 );
		
		return  movies;        
      
	}
	public Node getNodeMovie(GraphDatabaseService graph, String key){
		Index<Node> index = graph.index().forNodes(Keys.INDEXMOVIE);
		Node node = index.get(Keys.MOVIEKEY, key.toLowerCase()).getSingle();
		return node;
	}
}
